#include "http_task.h"
#include <etimer.h>
#include <process.h>
#include <stdlib.h>
#include <string.h>

#include "gprs_task.h"
#include "gsm.h"
#include "json.h"
#include "md5.h"
#include "net_api.h"
#include "time.h"
#include "uart.h"
#include "wifi.h"
#include "wifi_task.h"

#include "device_manage.h"

PROCESS(HttpGetTime_Process, "HttpGetTime");
PROCESS(HttpGetID_Process, "HttpGetID");

static my_cJSON *root = NULL;
static my_cJSON *code = NULL;
static my_cJSON *htime = NULL;
static my_cJSON *device_id = NULL;

static uint8_t i = 0;
static sWifiCmd wificmd;
static sGprsCmd gprscmd;
static char cmdBuf[30];
static char *prt;
static int pre_len = 0;
static struct etimer et;
static char *s = NULL;
static char res = 0;
static struct process *pro;
static uint32_t tmp_time;

static char time_str[11] = {'\0'};
static char time_md5[33] = {'\0'};
static char token[64] = {'\0'};
static uint8_t result[16];
static md5_ctx md5;

static void ByteToHexStr(const unsigned char *source, char *dest,
                         int sourceLen) {
  short i;
  unsigned char highByte, lowByte;

  for (i = 0; i < sourceLen; i++) {
    highByte = source[i] >> 4;
    lowByte = source[i] & 0x0f;

    highByte += 0x30;

    if (highByte > 0x39)
      dest[i * 2] = highByte + 0x27;
    else
      dest[i * 2] = highByte;

    lowByte += 0x30;
    if (lowByte > 0x39)
      dest[i * 2 + 1] = lowByte + 0x27;
    else
      dest[i * 2 + 1] = lowByte;
  }
  return;
}

void httpGetTimeSerialze() {
  prt = (char *)malloc(512);
  memset(prt, '\0', 512);
  strcat((char *)prt, "GET /api/weixiniot/get_time HTTP/1.1\r\n");
  strcat((char *)prt, "Host:xxx.com\r\n");	
  strcat((char *)prt, "Connection: keep-alive\r\n");
  strcat((char *)prt, "Accept: text/html;\r\n");
  strcat((char *)prt, "\r\n");
}

void httpGetIDSerialze() {
  uint32_t time;
  prt = (char *)malloc(512);
  memset(prt, '\0', 512);
  memset(time_str, '\0', strlen(time_str));
  memset(token, '\0', strlen(token));
  memset(time_md5, '\0', strlen(time_md5));
  time = RTC_GetCounter() - 28800;
  sprintf(time_str, "%d", time);
  strcat(token, time_str);
  strcat(token, Product_Key);
  md5_init(&md5);
  md5_update(&md5, token, strlen(token));
  md5_final(result, &md5);
  ByteToHexStr(result, time_md5, 16);

  sprintf((char *)prt,
          "GET /api/weixiniot/get_id?mac=%.8X&time=%d&token=%s&product_id=%s "
          "HTTP/1.1\r\n",
          uid.temp2, time, time_md5, Product_ID);
#ifndef TEST 
  strcat((char *)prt, "Host:loracall.jiazi-iot.com\r\n");	 
#else
  strcat((char *)prt, "Host:test-loracall.jiazi-iot.com\r\n");		 
#endif
  strcat((char *)prt, "Connection: keep-alive\r\n");
  strcat((char *)prt, "Accept: text/html;\r\n");
  strcat((char *)prt, "\r\n");
}

PROCESS_THREAD(HttpGetTime_Process, ev, data) {
  static struct etimer et;

  PROCESS_BEGIN();
  printf("HttpGetTime_Process start  \r\n");
  if (ev == PROCESS_EVENT_INIT) {
    pro = (struct process *)data;
  }

  if (netdevice_type == net_device_wifi) {
    i = 3;
    set_wificmdval(&wificmd, AT_CIPHTTP, AT_CIPHTTP_RES, &HttpGetTime_Process);
    wifisend_cmd(WifiCMD_Process, wificmd, i);
  } else {
    i = 1;
    set_gprscmdval(&gprscmd, GSM_CIPHTTP, GSM_CIPHTTP_RES, GSM_ERROE_RES,
                   &HttpGetTime_Process);
    gprssend_cmd(GprsCMD_Process, gprscmd, i);
    //		etimer_set(&et, 2000);
    //		PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
  }

  if (i == 0) {
    if (netdevice_type == net_device_wifi) {
      process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
      process_exit(&HttpGetTime_Process);
      free(prt);
      netstatus = net_idle;
      return PT_ENDED;
    } else {
      process_start(&Gprs_GetStatus_Process,
                    (process_data_t)&HttpGetTime_Process);
      tmp_time = HAL_GetTick();
      do {
        PROCESS_WAIT_EVENT();
      } while (ev != PROCESS_EVENT_CONTINUE &&
               (HAL_GetTick() - tmp_time < 10000));
      static uint8_t res;
      res = *(uint8_t *)data;
      if (res == 0) {
        process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
        process_exit(&HttpGetTime_Process);
        free(prt);
        netstatus = net_idle;
        return PT_ENDED;
      }
    }
  }

  httpGetTimeSerialze();

  i = 3;
  sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", strlen(prt));
  if (netdevice_type == net_device_wifi) {
    set_wificmdval(&wificmd, cmdBuf, ">", &HttpGetTime_Process);
    wifisend_cmd(WifiCMD_Process, wificmd, i);
  } else {
    set_gprscmdval(&gprscmd, cmdBuf, ">", GSM_ERROE_RES, &HttpGetTime_Process);
    gprssend_cmd(GprsCMD_Process, gprscmd, i);
  }
  if (i == 0) {
    process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
    process_exit(&HttpGetTime_Process);
    free(prt);
    netstatus = net_idle;
    return PT_ENDED;
  }

  if (netdevice_type == net_device_wifi) {
    Wifi_ClearRecive();
  } else {
    Gsm_ClearRecive();
  }
  netstatus = net_doing;
  uart_send((uint8_t *)prt, strlen(prt));
  if (netdevice_type == net_device_wifi) {
    process_start(&Wifi_GetIPD_Process, NULL);
  } else {
    process_start(&Gprs_GetIPD_Process, NULL);
  }

  pre_len = 0;
  tmp_time = HAL_GetTick();
  while ((HAL_GetTick() - tmp_time < 10000)) {
    if (fifo_get.Counter > 0) {
      if (pre_len == fifo_get.Counter) {
        break;
      } else {
        pre_len = fifo_get.Counter;
      }
    }
    etimer_set(&et, 1);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
  }
  if (netdevice_type == net_device_wifi) {
    process_exit(&Wifi_GetIPD_Process);
  } else {
    process_exit(&Gprs_GetIPD_Process);
  }
  memset(prt, '\0', strlen(prt));
  FIFO_Get(&fifo_get, prt, fifo_get.Counter);
  s = strstr((const char *)prt, "{");
  root = my_cJSON_Parse((const char *)s);
  if (root == NULL) {
    res = 0;
  } else {
    htime = my_cJSON_GetObjectItem(root, "time");
    if (htime == NULL) {
      res = 0;
    } else {
      res = 1;
      TimeDate_Setsec(htime->valueint + 28800);
    }
  }

  my_cJSON_Delete(root);

  i = 1;
  if (netdevice_type == net_device_wifi) {
    set_wificmdval(&wificmd, AT_CIPCLOSE, AT_CIPCLOSE_RES,
                   &HttpGetTime_Process);
    wifisend_cmd(WifiCMD_Process, wificmd, i);
  } else {
    set_gprscmdval(&gprscmd, GSM_CIPCLOSE, GSM_CIPCLOSE_RES, GSM_ERROE_RES,
                   &HttpGetTime_Process);
    gprssend_cmd(GprsCMD_Process, gprscmd, i);
  }
  process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);

  free(prt);
  netstatus = net_idle;
  printf("HttpGetTime_Process succeed  \r\n");
  PROCESS_END();
}

PROCESS_THREAD(HttpGetID_Process, ev, data) {
  PROCESS_BEGIN();

  res = 0;
  if (ev == PROCESS_EVENT_INIT) {
    pro = (struct process *)data;
  }

  if (netdevice_type == net_device_wifi) {
    i = 3;
    set_wificmdval(&wificmd, AT_CIPHTTP, AT_CIPHTTP_RES, &HttpGetID_Process);
    wifisend_cmd(WifiCMD_Process, wificmd, i);
  } else {
    i = 1;
    set_gprscmdval(&gprscmd, GSM_CIPHTTP, GSM_CIPHTTP_RES, GSM_ERROE_RES,
                   &HttpGetID_Process);
    gprssend_cmd(GprsCMD_Process, gprscmd, i);
    etimer_set(&et, 2000);
    PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER);
  }

  if (i == 0) {
    if (netdevice_type == net_device_wifi) {
      process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
      process_exit(&HttpGetTime_Process);
      free(prt);
      netstatus = net_idle;
      return PT_ENDED;
    } else {
      process_start(&Gprs_GetStatus_Process,
                    (process_data_t)&HttpGetID_Process);
      tmp_time = HAL_GetTick();
      do {
        PROCESS_WAIT_EVENT();
      } while (ev != PROCESS_EVENT_CONTINUE &&
               (HAL_GetTick() - tmp_time < 10000));
      static uint8_t res;
      res = *(uint8_t *)data;
      if (res == 0) {
        process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
        process_exit(&HttpGetTime_Process);
        free(prt);
        netstatus = net_idle;
        return PT_ENDED;
      }
    }
  }
  httpGetIDSerialze();

  i = 3;
  sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", strlen(prt));
  if (netdevice_type == net_device_wifi) {
    set_wificmdval(&wificmd, cmdBuf, ">", &HttpGetID_Process);
    wifisend_cmd(WifiCMD_Process, wificmd, i);
  } else {
    set_gprscmdval(&gprscmd, cmdBuf, ">", GSM_ERROE_RES, &HttpGetID_Process);
    gprssend_cmd(GprsCMD_Process, gprscmd, i);
  }
  if (i == 0) {
    process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
    process_exit(&HttpGetID_Process);
    free(prt);
    netstatus = net_idle;
    return PT_ENDED;
  }
  netstatus = net_doing;
  Wifi_ClearRecive();
  uart_send((uint8_t *)prt, strlen(prt));
  if (netdevice_type == net_device_wifi) {
    process_start(&Wifi_GetIPD_Process, NULL);
  } else {
    process_start(&Gprs_GetIPD_Process, NULL);
  }
  pre_len = 0;
  tmp_time = HAL_GetTick();
  while ((HAL_GetTick() - tmp_time < 10000)) {
    if (fifo_get.Counter > 0) {
      if (pre_len == fifo_get.Counter) {
        break;
      } else {
        pre_len = fifo_get.Counter;
      }
    }
    etimer_set(&et, 1);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
  }
  if (netdevice_type == net_device_wifi) {
    process_exit(&Wifi_GetIPD_Process);
  } else {
    process_exit(&Gprs_GetIPD_Process);
  }
  memset(prt, '\0', strlen(prt));
  FIFO_Get(&fifo_get, prt, fifo_get.Counter);
  s = strstr((const char *)prt, "{");

  root = my_cJSON_Parse((const char *)s);
  if (root == NULL) {
    res = 0;
  } else {
    code = my_cJSON_GetObjectItem(root, "code");
    if (code == NULL) {
      res = 0;
    } else {
      if (code->valueint == 100) {
        res = 1;
        device_id = my_cJSON_GetObjectItem(root, "device_id");
        strncpy((char *)cfg_data.Val.Device_id,
                (const char *)device_id->valuestring, 16);
        cfg_data.Val.Device_id[16] = '\0';
        write_cfg(&cfg_data);
      } else {
        res = 0;
      }
    }
  }

  my_cJSON_Delete(root);

  i = 1;
  if (netdevice_type == net_device_wifi) {
    set_wificmdval(&wificmd, AT_CIPCLOSE, AT_CIPCLOSE_RES, &HttpGetID_Process);
    wifisend_cmd(WifiCMD_Process, wificmd, i);
  } else {
    set_gprscmdval(&gprscmd, GSM_CIPCLOSE, GSM_CIPCLOSE_RES, GSM_ERROE_RES,
                   &HttpGetID_Process);
    gprssend_cmd(GprsCMD_Process, gprscmd, i);
  }

  process_post(pro, PROCESS_EVENT_CONTINUE, (process_data_t)&res);
  free(prt);
  netstatus = net_idle;
  PROCESS_END();
}
